#ifndef __CORE_COMMON_STRING_H_INCLUDE__
#define __CORE_COMMON_STRING_H_INCLUDE__

#include <core/common/platform.h>

namespace core{ namespace common
{
	typedef std::list<std::string>   StringList;
	typedef std::vector<std::string> StringArray;
	typedef std::map<std::string, std::string> StringMap;
	typedef std::set<std::string> StringSet;

	class CORE_COMMON_API__ String
	{
	public:
		// as ParserNumber for 64-bit integer
		static int64  atoi64( const char *value );
		static bool   isSpace( const char value );
		static bool   isDigit( const char value );
		static bool   isAlphaNumber( const char value );
		
		// support string format: Y-m-d H:i:s
		// or Y-m-d H-i-s
		// or Y.m.d H.i.s
		// or Y.m.d-H.i.s
		static time_t toTimestamp( const std::string &timeValue, bool gmtTime = false );

		// to Y-m-d H:i:s date format
		static std::string  formatTime( time_t tmValue );
		static std::string  formatTime( int64 microValue, bool milliSeconds );
		static std::string  formatTime( const std::string &fmt, time_t tmValue, bool includeMark = false );
		static std::string  formatMicroTime( const std::string &fmt, int64 microValue, bool includeMark = false );
		static std::string  formatStandardTime( time_t tmValue, bool gmt );
		static std::string  formatLongTime( time_t tmValue, bool gmt );
		static std::string  getLocalTime( bool milliSeconds );
		static std::string  formatRelativeTime( int64 microValue );
		// xx.xx.xx.xx ip version-4 format
		static std::string  formatIpv4( uint32 ipv4 );
		static std::string  formatFileSize( uint64 fileSize );
		static std::string  formatSpeed( uint64 speed, bool unitBits, bool shortName );
		static std::string  formatTimeLength( time_t timeLength );

		// xx:xx:xx:xx:xx:xx mac address format
		static std::string formatMacAddress( uint8 *macAddress );

		// as sprintf format %s,%d,%u,%I64d,%lld ...
		static std::string  format( __FMT_PRINT_PARAM__ const char *fmt, ... ) __FMTCHECK__(printf, 1, 2);
		static std::string  formatV( const char *fmt, va_list argList );
		static std::string &appendFormat( std::string &strOrg, __FMT_PRINT_PARAM__ const char *fmt, ... ) __FMTCHECK__(printf, 2, 3);
		
		// make string upper or lower
		static std::string  toUpper( const std::string &source );
		static std::string  toLower( const std::string &source );
		static std::string &makeUpper( std::string &source );
		static std::string &makeLower( std::string &source );

		// trim invisible characters such as blank,tab etc.
		static std::string &trim( std::string &source );
		static std::string &trimLeft( std::string &source );
		static std::string &trimRight( std::string &source );

		// replace all old strings to new string
		static int replace( std::string &org, const std::string &old, const std::string &newString );
		static std::string replaceTo( const std::string &org, const std::string &old, const std::string &newString );
		static int replaceNonAscii( std::string &org, const char newChar );
		static std::string  replaceNonAsciiTo( const std::string &org, const char newChar );

		// split string to array, such as "a;b;c;;d;" => Array{"a","b","c","","d"}
		static int split( const std::string &content, 
			core::common::StringList &values,
			const char key,
			int maxItems = -1,
			bool ignoreEmpty = false,
			size_t contentLength = std::string::npos );

		static int split( const std::string &content, 
			core::common::StringList &values,
			const std::string &key,
			int maxItems = -1,
			bool ignoreEmpty = false,
			size_t contentLength = std::string::npos );

		static int split( const std::string &content,
			core::common::StringArray &values,
			const char key,
			int maxItems = -1,
			bool ignoreEmpty = false,
			size_t contentLength = std::string::npos );

		static int split( const std::string &content,
			core::common::StringArray &values,
			const std::string &key,
			int maxItems = -1,
			bool ignoreEmpty = false,
			size_t contentLength = std::string::npos );

		// parse attribute string, format such as "a=b;c=d;e=f" => Map{"a"=>"b", "c"=>"d","e"=>"f"}
		static int parseAttributes( const std::string &content, 
			core::common::StringMap &attributes,
			const char separatorKey = ';', 
			const char valueKey = '=', 
			bool keyLowCase = false,
			bool trimKey = false,
			bool trimValue = false );

		// compare string case-sensitive or case-insensitive
		static int compare  ( const std::string &str1, const std::string &str2, bool ignoreCase = false );
		static int compareTo ( const char *str1, const char *str2, bool ignoreCase = false );
		static int compareVersion( const std::string &version1, const std::string &version2, const std::string &separator );

		// string => integer
		static uint32 parseNumber( const std::string &value, const uint32 defaultValue );
		static int32  parseNumber( const std::string &value, const int32  defaultValue );
		static uint64 parseNumber( const std::string &value, const uint64 defaultValue );
		static int64  parseNumber( const std::string &value, const int64  defaultValue );
		static double parseNumber( const std::string &value, const double defaultValue );
		static uint64 parseNumberX64( const std::string &value, const uint64 defaultValue );
		static int64  parseLocalTime( const std::string &timeValue ); // such as 2013-02-23 12:33:23.1238873

		// integer => string
		static std::string fromNumber( const uint64 number );
		static std::string fromNumber( const int64  number );
		static std::string fromNumber( const uint32 number );
		static std::string fromNumber( const int32  number );
		static std::string fromNumber( const double number );

		// base64 format encoding
		static size_t base64EncodeSize( size_t length );
		static size_t base64DecodeSize( size_t length );
		static bool base64Encode( const uint8 *source, size_t sourceLength, char *dest, size_t &destLength );
		static bool base64Decode( const char *source, size_t sourceLength, uint8 *dest, size_t &destLength );
		static std::string base64Encode( const std::string &source );
		static std::string base64Decode( const std::string &source );

		static std::string urlEncode( const std::string &name );
		static std::string urlEncodeNonAscii( const std::string &name );
		static std::string urlDecode( const std::string &name );

		// byte to hex string
		static std::string bytesToHexString( const uint8 *data, size_t length, bool upperCase );
		static std::string bytesToHexString( const std::string &data, bool upperCase );
		static std::string hexStringToBytes( const std::string &data );
		static uint8 *hexStringToBytes( const std::string &data, uint8 *buffer, size_t length );

		// JSON
		static std::string &jsonEncode( std::string &value );

		static bool parseUrl( const std::string &url, 
			std::string &protocol,
			std::string &host,
			uint16 &port,
			std::string &path,
			std::string &file );
		static int normalizeUrlPath( std::string &path );
	};
}}

#endif //__CORE_COMMON_STRING_H_INCLUDE__
